package taskscheduler.components;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

import taskscheduler.components.Item.ItemType;

public class Scheduler implements Runnable{
	
	private List<Order> orders = new ArrayList<Order>();
	private List<Item> itemsType1 = new ArrayList<Item>();
	private List<Item> itemsType2 = new ArrayList<Item>();
	private List<Item> scheduled = new ArrayList<Item>();
	
	private List<SchedulerTask> tasks = new ArrayList<SchedulerTask>();
	
	private int OrderCount = 0;
	
	private Thread schedulerThread = new Thread(this, "SchedulerThread");
	private boolean toProcess = false;
	
	
	public enum SchedulerTaskType {
		ADD_ORDER, FINISH_ORDER, SECOND_COURSE;
	}
	
	private class SchedulerTask {
		private SchedulerTaskType type;
		private Object parameter1 = null;
		
		public SchedulerTask(SchedulerTaskType type, Object parameter1) {
			this.type = type;
			this.parameter1 = parameter1;
		}
		
		
		public SchedulerTask(SchedulerTaskType type) {
			this.type = type;
		}


		public SchedulerTaskType getType() {
			return type;
		}
		public void setType(SchedulerTaskType type) {
			this.type = type;
		}
		public Object getParameter1() {
			return parameter1;
		}
		public void setParameter1(Object parameter1) {
			this.parameter1 = parameter1;
		}
	}
	
	public Scheduler() {
		schedulerThread.start();
	}
	
	public void command(SchedulerTaskType type) {
		tasks.add(new SchedulerTask(type));
		toProcess = true;
	}
	
	public void command(SchedulerTaskType type, Object parameter) {
		tasks.add(new SchedulerTask(type, parameter));
		toProcess = true;
	}
	
	public List<Item> getFlux() throws SchedulerSleepingException{
		if(toProcess)
			throw new SchedulerSleepingException();
		return scheduled;
	}
	
	private void done(Order order){
		if(order==null) {
			Order firstorder = scheduled.get(0).getOrder();
			
			while(scheduled.get(0).getOrder()==firstorder)
				scheduled.remove(0);
			System.out.println(firstorder.getName() + " finished");
		}
		
		else {
			boolean start = false;
			for (int i = 0; i < scheduled.size(); i++) {
				if(scheduled.get(i).getOrder()==order) {
					scheduled.remove(i);
					start = true;
				}
				else if(scheduled.get(i).getOrder()!=order && start)
					break;
			}
			System.out.println(order.getName() + " finished");
			
		}
		
	}

	
	private void processTask() {
		while (tasks.size() != 0 ) {
			SchedulerTask task = tasks.get(0);
			
			Order order = null; 
			
			switch (task.getType()) {
				case ADD_ORDER:
					order = (Order) task.getParameter1();
					order.setId(++OrderCount);
					orders.add(order);
					System.out.println(order.getName() + " added");
					break;
				case FINISH_ORDER:
					order = (Order) task.getParameter1();
					done(order);
					break;
					
				default:
					
					break;
			}
			tasks.remove(0);
		}
		processOrder();

	}
	
	private void processOrder() {

		while(orders.size()!=0) {
			Order order = orders.get(0);
			
			if(order.getOrderList().size()==0) {
				orders.remove(0);
				continue;
			}
			
			if(!order.getClass().getSimpleName().equals("Table")) {
				itemsType2.addAll(order.getOrderList());
				orders.remove(0);
				continue;
			}
			
			
			Iterator iterator = order.getOrderList().iterator(); 
			while(iterator.hasNext()) {
				Item item = (Item) iterator.next();
				if(item.getType()==ItemType.type1) 
					itemsType1.add(item);
				else if(item.getType()==ItemType.type2) 
					itemsType2.add(item);
			}
			
			orders.remove(0);
		}
		
		scheduled.addAll(itemsType1);
		scheduled.addAll(itemsType2);
		itemsType1.clear();
		itemsType2.clear();
		toProcess = false;
	}
	


	@Override
	public void run() {

		while(orders.size()==0) {
			try {
				schedulerThread.sleep(1000);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			processTask();
		}

	}

}
